#include <srs_app_conn.hpp>

#include <srs_kernel_log.hpp>
#include <srs_kernel_error.hpp>
#include <srs_app_utility.hpp>

IConnectionManager::IConnectionManager() {
}

IConnectionManager::~IConnectionManager() {
}

SrsConnection::SrsConnection(IConnectionManager* cm, st_netfd_t c) {
    id = 0;
    manager = cm;
    stfd = c;
    disposed = false;
    expired = false;

    // the client thread should reap itself,
    // so we never use joinable.
    // TODO: FIXME: maybe other thread need to stop it.
    pthread = new SrsOneCycleThread("conn", this);
}

SrsConnection::~SrsConnection() {
    dispose();

    srs_freep(pthread);
}

void SrsConnection::dispose() {
    if (disposed) {
        return;
    }

    disposed = true;

    /**
     * when delete the connection, stop the connection,
     * close the underlayer socket, delete the thread.
     */
    srs_close_stfd(stfd);
}

int SrsConnection::start() {
    return pthread->start();
}

int SrsConnection::cycle() {
    int ret = ERROR_SUCCESS;

    _srs_context->generate_id();
    id = _srs_context->get_id();

    ip = srs_get_peer_ip(st_netfd_fileno(stfd));

    ret = do_cycle();

    // if socket io error, set to closed.
    if (srs_is_client_gracefully_close(ret)) {
        ret = ERROR_SOCKET_CLOSED;
    }

    // success.
    if (ret == ERROR_SUCCESS) {
        srs_trace("client finished.");
    }

    // client close peer.
    if (ret == ERROR_SOCKET_CLOSED) {
        srs_warn("client disconnect peer. ret=%d", ret);
    }

    return ERROR_SUCCESS;
}

void SrsConnection::on_thread_stop() {
    // TODO: FIXME: never remove itself, use isolate thread to do cleanup.
    manager->remove(this);
}

int SrsConnection::srs_id() {
    return id;
}

void SrsConnection::expire() {
    expired = true;
}


